// 这个是对锁的封装  --- 锁的组件

//防止头文件重复包含 , 这里使用现代写法
#pragma once 

#include <iostream>
#include <pthread.h>

// 锁的组件
namespace MutexModel
{

    class Mutex
    {
    public:
        // 外部定义锁对象 , 构造时创建锁
        Mutex()
        {
            // 创建锁
            pthread_mutex_init(&_mutex, nullptr);
        }

        // 加锁
        void Lock()
        {
            pthread_mutex_lock(&_mutex);
        }

        // 解锁
        void Unlock()
        {
            pthread_mutex_unlock(&_mutex);
        }

        //方便外部类使用我的 _mutex 私有成员 , 所以我提供Get函数
        pthread_mutex_t& GetLock()
        {
            return _mutex;
        }

        ~Mutex()
        {
            // 销毁锁
            pthread_mutex_destroy(&_mutex);
        }

    private:
        pthread_mutex_t _mutex; // 定义锁类型变量
    };

    // 一般我们都喜欢这样用 , RAII风格
    // 守护锁 , 自动加锁 , 解锁
    class LockGuard
    {
    public:
        // 外部传一把锁 , 我可以帮你完成 : 加锁 , 解锁
        // 你只要在外部定义我的类对象 , 就会进行加锁 , 只有对象释放时才解锁
        LockGuard(Mutex &mutex)
            : _mutex(mutex)
        {
            _mutex.Lock();
            //std::cout << " Lock Success ! " << std::endl;
        }

        // 我析构时 , 给你解锁就行 , 我析构了也会调用你的析构最终锁就销毁了
        ~LockGuard()
        {
            _mutex.Unlock();
            //std::cout << " UnLock Success ! " << std::endl;
        }

    private:
        // 定义一个锁类的对象 , 对象里面有各种方法 , 并且我的类对象结束后会调用你的析构
        Mutex &_mutex; // & -- 引用减少拷贝
    };
}